
#include "../Almonaster.h"
#include "../GameEngine/GameEngine.h"
#include <stdio.h>

#include "../HtmlRenderer/HtmlRenderer.h"

#define Write m_pHttpResponse->WriteText

// Render the OpenGameList page
int HtmlRenderer::Render_OpenGameList() {

	// Almonaster 2.0
	// Copyright (C) 1998 Max Attar Feingold (maf6@cornell.edu)
	//
	// This program is free software; you can redistribute it and/or
	// modify it under the terms of the GNU General Public License
	// as published by the Free Software Foundation; either version 2
	// of the License, or (at your option) any later version.

	// This program is distributed in the hope that it will be useful,
	// but WITHOUT ANY WARRANTY; without even the implied warranty of
	// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	// GNU General Public License for more details.
	//
	// You should have received a copy of the GNU General Public License
	// along with this program; if not, write to the Free Software
	// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

	INITIALIZE_EMPIRE

	IHttpForm* pHttpForm;

	int i, iErrCode;
	bool bConfirmPage = false;
	int iGameClassKey = NO_KEY, iGameNumber = NO_KEY;
	const char* pszPassword = NULL;

	// Handle a submission
	if (m_bOwnPost && !m_bRedirection) {

		const char* pszStart = NULL;
		if ((pHttpForm = m_pHttpRequest->GetFormBeginsWith ("Enter")) != NULL && 
			(pszStart = pHttpForm->GetName()) != NULL &&
			sscanf (pszStart, "Enter%d.%d", &iGameClassKey, &iGameNumber) == 2) {

			char pszForm[128];
			sprintf (pszForm, "Pass%i.%i", iGameClassKey, iGameNumber);

			if ((pHttpForm = m_pHttpRequest->GetForm (pszForm)) != NULL) {
				pszPassword = pHttpForm->GetValue();
			}

			bool bConfirm = false;
			int iRetVal = OK;

			if (m_pHttpRequest->GetForm ("Confirm") == NULL) {
				iRetVal = g_pGameEngine->GetEmpireOption (m_iEmpireKey, CONFIRM_ON_ENTER_OR_QUIT_GAME, &bConfirm);
			}

			if (iRetVal == OK) {

				if (bConfirm) {
					bConfirmPage = true;
				} else {

					// Enter game!
					int iNumUpdatesTranspired;
					iErrCode = g_pGameEngine->EnterGame (
						iGameClassKey,
						iGameNumber,
						m_iEmpireKey,
						pszPassword == NULL ? "" : pszPassword,
						&iNumUpdatesTranspired
						);

					HANDLE_ENTER_GAME_OUTPUT (iErrCode);
				}
			}
		}
	}

	SYSTEM_REDIRECT_ON_SUBMIT

	if (bConfirmPage) {

		bool bFlag;

		// Make sure game exists
		iErrCode = g_pGameEngine->DoesGameExist (iGameClassKey, iGameNumber, &bFlag);
		if (iErrCode != OK || !bFlag) {
			AddMessage ("That game no longer exists");
			bConfirmPage = false;
		}
	}

	SYSTEM_OPEN (false)

	if (bConfirmPage) {

		//
		// Don't want a page switch system because guest empires would need to submit an extra form
		//

		char pszGameClassName [MAX_FULL_GAME_CLASS_NAME_LENGTH];

		iErrCode = g_pGameEngine->GetGameClassName (iGameClassKey, pszGameClassName);
		if (iErrCode != OK) {
			AddMessage ("That game no longer exists");
			return Redirect (OPEN_GAME_LIST);
		}

		
	Write ("<input type=\"hidden\" name=\"Pass", sizeof ("<input type=\"hidden\" name=\"Pass") - 1);
	Write (iGameClassKey); 
	Write (".", sizeof (".") - 1);
	Write (iGameNumber); 
	Write ("\" value=\"", sizeof ("\" value=\"") - 1);
	if (pszPassword != NULL) {
			Write (pszPassword);
		} 
	Write ("\"><input type=\"hidden\" name=\"Confirm\" value=\"1\"><p>Are you sure that you want to enter <strong>", sizeof ("\"><input type=\"hidden\" name=\"Confirm\" value=\"1\"><p>Are you sure that you want to enter <strong>") - 1);
	Write (pszGameClassName);
		
	Write (" ", sizeof (" ") - 1);
	Write (iGameNumber); 
	Write ("</strong>?<p>", sizeof ("</strong>?<p>") - 1);
	WriteButton (BID_CANCEL);

		char pszEnter[256];
		sprintf (pszEnter, "Enter%i.%i", iGameClassKey, iGameNumber);

		WriteButtonString (m_iButtonKey, "EnterGame", "Enter", pszEnter);

	} else {

		// Get open games
		int iNumOpenGames = 0, * piGameClass, * piGameNumber;

		iErrCode = g_pGameEngine->GetOpenGames (&piGameClass, &piGameNumber, &iNumOpenGames);
		if (iErrCode != OK) {
			
	Write ("<h3>The open game list could not be read. The error was ", sizeof ("<h3>The open game list could not be read. The error was ") - 1);
	Write (iErrCode); 
	Write ("</h3>", sizeof ("</h3>") - 1);
	}

		else if (iNumOpenGames == 0) {
			
	Write ("<h3>There are no open games on this server</h3>", sizeof ("<h3>There are no open games on this server</h3>") - 1);
	}

		else {

			// Update the open games
			int j, iGameClass, iGameNumber;

			int* piSuperClassKey, iNumSuperClasses;
			bool bDraw = false;
			Check (g_pGameEngine->GetSuperClassKeys (&piSuperClassKey, &iNumSuperClasses));

			if (iNumSuperClasses == 0) {
				
	Write ("<h3>There are no open games on this server</h3>", sizeof ("<h3>There are no open games on this server</h3>") - 1);
	} else {

				// Create the game table
				int** ppiTable = (int**) StackAlloc ((iNumSuperClasses + 1) * 3 * sizeof (int*));
				int** ppiGameClass = ppiTable + iNumSuperClasses + 1;
				int** ppiGameNumber = ppiGameClass + iNumSuperClasses + 1;

				// Create the game
				for (i = 0; i < iNumSuperClasses + 1; i ++) {
					ppiTable[i] = (int*) StackAlloc ((iNumOpenGames + 1) * 3 * sizeof (int));
					ppiTable[i][iNumOpenGames] = 0;

					ppiGameClass[i] = ppiTable[i] + iNumOpenGames + 1;
					ppiGameNumber[i] = ppiGameClass[i] + iNumOpenGames + 1;
				}

				// Fill in the table
				int iSuperClassKey;
				bool bFlag;

				for (i = 0; i < iNumOpenGames; i ++) {

					iGameClass = piGameClass[i];
					iGameNumber = piGameNumber[i];

					// Check everything
					if (g_pGameEngine->CheckGameForUpdates (iGameClass, iGameNumber, &bFlag) == OK &&
						g_pGameEngine->DoesGameExist (iGameClass, iGameNumber, &bFlag) == OK && bFlag &&
						g_pGameEngine->IsGameOpen (iGameClass, iGameNumber, &bFlag) == OK && bFlag &&
						g_pGameEngine->IsEmpireInGame (iGameClass, iGameNumber, m_iEmpireKey, &bFlag) == OK && !bFlag &&
						g_pGameEngine->GameAccessCheck (iGameClass, iGameNumber, m_iEmpireKey, NULL, VIEW_GAME, &bFlag) == OK && bFlag &&
						g_pGameEngine->GetGameClassSuperClassKey (iGameClass, &iSuperClassKey) == OK) {

						for (j = 0; j < iNumSuperClasses; j ++) {
							if (piSuperClassKey[j] == iSuperClassKey) {

								// We found a match, so write down the game in question
								ppiTable [j][ppiTable [j][iNumOpenGames]] = i;

								ppiGameClass[j][ppiTable [j][iNumOpenGames]] = iGameClass;
								ppiGameNumber[j][ppiTable [j][iNumOpenGames]] = iGameNumber;

								ppiTable [j][iNumOpenGames] ++;
								bDraw = true;
								break;
							}
						}

						if (j == iNumSuperClasses) {

							// No superclass was found, so it must be a personal game
							ppiTable [iNumSuperClasses][ppiTable [iNumSuperClasses][iNumOpenGames]] = i;

							ppiGameClass[iNumSuperClasses][ppiTable [iNumSuperClasses][iNumOpenGames]] = iGameClass;
							ppiGameNumber[iNumSuperClasses][ppiTable [iNumSuperClasses][iNumOpenGames]] = iGameNumber;

							ppiTable [iNumSuperClasses][iNumOpenGames] ++;
							bDraw = true;
						}
					}
				}

				if (!bDraw) {
					
	Write ("<h3>There are no open games available to your empire</h3>", sizeof ("<h3>There are no open games available to your empire</h3>") - 1);
	} else {

					
	Write ("<p><h3>Join an open game:</h3>", sizeof ("<p><h3>Join an open game:</h3>") - 1);
	Variant* pvGameClassInfo = NULL;
					int iBegin, iCurrentGameClass, iNumGamesInSuperClass, iNumToSort;

					if (ppiTable [iNumSuperClasses][iNumOpenGames] > 0) {

						
	Write ("<p><h3>Personal Games:</h3>", sizeof ("<p><h3>Personal Games:</h3>") - 1);
	WriteOpenGameListHeader (m_vTableColor.GetCharPtr());

						iNumGamesInSuperClass = ppiTable[iNumSuperClasses][iNumOpenGames];

						// Sort games by gameclass
						Algorithm::QSortThreeAscending<int, int, int> (
							ppiGameClass[iNumSuperClasses],
							ppiGameNumber[iNumSuperClasses],
							ppiTable[iNumSuperClasses],
							iNumGamesInSuperClass
							);

						// Sort games by gamenumber
						iBegin = 0;
						iCurrentGameClass = ppiGameClass[iNumSuperClasses][0];

						for (j = 1; j < iNumGamesInSuperClass; j ++) {

							if (ppiGameClass[iNumSuperClasses][j] != iCurrentGameClass) {

								iNumToSort = j - iBegin;
								if (iNumToSort > 1) {
									Algorithm::QSortThreeAscending<int, int, int> (
										ppiGameNumber[iNumSuperClasses] + iBegin,
										ppiGameClass[iNumSuperClasses] + iBegin,
										ppiTable[iNumSuperClasses] + iBegin,
										iNumToSort
										);
								}

								iBegin = j;
								iCurrentGameClass = ppiGameClass[iNumSuperClasses][j];
							}
						}

						iNumToSort = j - iBegin;
						if (iNumToSort > 1) {

							Algorithm::QSortThreeAscending<int, int, int> (
								ppiGameNumber[iNumSuperClasses] + iBegin,
								ppiGameClass[iNumSuperClasses] + iBegin,
								ppiTable[iNumSuperClasses] + iBegin,
								iNumToSort
								);
						}

						for (j = 0; j < ppiTable[iNumSuperClasses][iNumOpenGames]; j ++) {

							iGameClass = ppiGameClass[iNumSuperClasses][j];
							iGameNumber = ppiGameNumber[iNumSuperClasses][j];

							if (g_pGameEngine->GetGameClassData (iGameClass, &pvGameClassInfo) == OK) {

								// Best effort
								iErrCode = WriteOpenGameListData (
									iGameClass,
									iGameNumber, 
									pvGameClassInfo,
									false
									);
							}

							if (pvGameClassInfo != NULL) {
								g_pGameEngine->FreeData (pvGameClassInfo);
								pvGameClassInfo = NULL;
							}
						}

						
	Write ("</table>", sizeof ("</table>") - 1);
	}

					Variant vName;
					for (i = 0; i < iNumSuperClasses; i ++) {

						if (ppiTable [i][iNumOpenGames] > 0 && 
							g_pGameEngine->GetSuperClassName (piSuperClassKey[i], &vName) == OK) {

							
	Write ("<p><h3>", sizeof ("<p><h3>") - 1);
	Write (vName.GetCharPtr()); 
	Write (":</h3>", sizeof (":</h3>") - 1);
	WriteOpenGameListHeader (m_vTableColor.GetCharPtr());

							iNumGamesInSuperClass = ppiTable[i][iNumOpenGames];

							// Sort games by gameclass
							Algorithm::QSortThreeAscending<int, int, int> (
								ppiGameClass[i],
								ppiGameNumber[i],
								ppiTable[i],
								iNumGamesInSuperClass
								);

							// Sort games by gamenumber
							iBegin = 0;
							iCurrentGameClass = ppiGameClass[i][0];

							for (j = 1; j < iNumGamesInSuperClass; j ++) {

								if (ppiGameClass[i][j] != iCurrentGameClass) {

									iNumToSort = j - iBegin;
									if (iNumToSort > 1) {
										Algorithm::QSortThreeAscending<int, int, int> (
											ppiGameNumber[i] + iBegin,
											ppiGameClass[i] + iBegin,
											ppiTable[i] + iBegin,
											iNumToSort
											);
									}

									iBegin = j;
									iCurrentGameClass = ppiGameClass[i][j];
								}
							}

							iNumToSort = j - iBegin;
							if (iNumToSort > 1) {

								Algorithm::QSortThreeAscending<int, int, int> (
									ppiGameNumber[i] + iBegin,
									ppiGameClass[i] + iBegin,
									ppiTable[i] + iBegin,
									iNumToSort
									);
							}

							for (j = 0; j < iNumGamesInSuperClass; j ++) {

								iGameClass = ppiGameClass[i][j];
								iGameNumber = ppiGameNumber[i][j];

								if (g_pGameEngine->GetGameClassData (iGameClass, &pvGameClassInfo) == OK) {

									WriteOpenGameListData (
										iGameClass, 
										iGameNumber, 
										pvGameClassInfo,
										false
										);
								}

								if (pvGameClassInfo != NULL) {
									g_pGameEngine->FreeData (pvGameClassInfo);
									pvGameClassInfo = NULL;
								}
							}

							
	Write ("</table>", sizeof ("</table>") - 1);
	}
					}
				}

				g_pGameEngine->FreeKeys (piSuperClassKey);
			}

			delete [] piGameClass;
			delete [] piGameNumber;
		}
	}

	SYSTEM_CLOSE


}